/*
 * Toedo
 * Copyright (C) 2009-2010 J. Devauchelle and contributors.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 3 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

package org.toedo.gui.views;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.part.ViewPart;
import org.toedo.controllers.Controller;
import org.toedo.controllers.DataController;
import org.toedo.gui.translations.Messages;
import org.toedo.model.Tag;
import org.toedo.model.enums.SortDirection;
import org.toedo.preferences.PreferenceConstants;
import org.toedo.Activator;

public abstract class BaseNoteListViewPart extends ViewPart {

	protected Composite mParent;
	
	protected TableViewer mViewer = null;
	
	protected Table mFixedTagsList = null;
	protected Table mTagsList = null;
	
	protected TableItem mAllTableItem;
	protected TableItem mUnTaggedTableItem;
	
	protected DisplayMode mCurrentDisplayMode = DisplayMode.EnAll;
	protected List<Tag> mCurrentSelectedTagList = null;
	
	protected Image mTag;
	protected Image mNoTag;
	protected Image mEmptyTag;
	
	protected Image mTagsImage;
	protected Image mAttachmentsImage;
	protected Image mDeleteImage;
	
	protected Image mSortUpImage;
	protected Image mSortDownImage;
	
	protected TableColumn mTagsListColumn;
	
	protected SashForm mForm;
	
	protected Menu mListMenu = null;
	
	protected enum DisplayMode {
		EnAll,
		EnUnTagged,
		EnFiltered
	}
	
	public BaseNoteListViewPart() {
		Activator.getDefault();
		mTag = Activator.getImageDescriptor("/icons/tag-20.png").createImage(); //$NON-NLS-1$
		mNoTag = Activator.getImageDescriptor("/icons/notag-20.png").createImage(); //$NON-NLS-1$
		mEmptyTag = Activator.getImageDescriptor("/icons/empty-20.png").createImage(); //$NON-NLS-1$
		
		mTagsImage = Activator.getImageDescriptor("/icons/tag-16.png").createImage(); //$NON-NLS-1$
		mAttachmentsImage = Activator.getImageDescriptor("/icons/attachement-16.png").createImage(); //$NON-NLS-1$
		mDeleteImage = Activator.getImageDescriptor("/icons/delete-16.png").createImage(); //$NON-NLS-1$
		
		mSortUpImage = Activator.getImageDescriptor("/icons/sort-up-16.png").createImage(); //$NON-NLS-1$
		mSortDownImage = Activator.getImageDescriptor("/icons/sort-down-16.png").createImage(); //$NON-NLS-1$
		
		mCurrentSelectedTagList = new ArrayList<Tag>();
	}
	
	protected abstract int getBaseNoteCountByTag(Tag tag);
	protected abstract String getAllTableItemText();
	protected abstract String getUnTaggedTableItemText();
	
	protected abstract SortDirection getTagsSortDirection();
	protected abstract void setTagsSortDirection(SortDirection value);
	protected abstract void fireTagsSortEvent();
	
	protected abstract void openMenuHandler(SelectionEvent e);
	protected abstract void manageTagsMenuHandler(SelectionEvent e);
	protected abstract void manageAttachmentsMenuHandler(SelectionEvent e);
	protected abstract void deleteMenuHandler(SelectionEvent e);
	
	@Override
	public void createPartControl(Composite parent) {
		mParent = parent;
		
		mForm = new SashForm(mParent, SWT.HORIZONTAL);
		mForm.setLayout(new FillLayout());
		
		Composite leftPanel = new Composite(mForm, SWT.NONE);
		leftPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		GridLayout leftGL = new GridLayout(1, false);
		leftGL.marginRight = 0;
		leftPanel.setLayout(leftGL);
		
		mFixedTagsList = new Table(leftPanel, SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL);
		mFixedTagsList.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
		
		mFixedTagsList.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event event) {
				if (mFixedTagsList.getSelection().length > 0) {
					TableItem item = mFixedTagsList.getSelection()[0];
					
					if (item == mAllTableItem) {
						mCurrentDisplayMode = DisplayMode.EnAll;
						mCurrentSelectedTagList.clear();
					} else if (item == mUnTaggedTableItem) {
						mCurrentDisplayMode = DisplayMode.EnUnTagged;
						mCurrentSelectedTagList.clear();
					}
					mTagsList.setSelection(-1);
				}
				
				mViewer.refresh();
			}
		});
		
		mTagsList = new Table(leftPanel, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
		mTagsList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));		
		
		mTagsListColumn = new TableColumn(mTagsList, SWT.NONE);
		mTagsListColumn.setText(Messages.TaskListView_ColumnTags);
		
		mTagsListColumn.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				setTagSortDirection();
			}
		});
		
		mTagsList.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event event) {
				
				if (mTagsList.getSelection().length > 0) {
					mCurrentSelectedTagList.clear();
					mCurrentDisplayMode = DisplayMode.EnFiltered;

					for (TableItem tableItem : mTagsList.getSelection()) {
						mCurrentSelectedTagList.add((Tag) tableItem.getData());
						mFixedTagsList.setSelection(-1);
					}
				} else {
					mCurrentDisplayMode = DisplayMode.EnAll;
					mCurrentSelectedTagList.clear();
					mFixedTagsList.setSelection(mAllTableItem);
				}
				
				mViewer.refresh();
			}
		});
		
		mTagsList.addControlListener(new ControlAdapter() {
			public void controlResized(ControlEvent e) {
				int width = mTagsList.getClientArea().width - mTagsList.getVerticalBar().getSize().x;				
				mTagsListColumn.setWidth(width);				
			}
		});
		
		mTagsList.setHeaderVisible(true);
		
		Composite rightPanel = new Composite(mForm, SWT.NONE);
		rightPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		GridLayout rightGL = new GridLayout(1, false);
		rightGL.marginLeft = 0;
		rightPanel.setLayout(rightGL);
		
		mViewer = new TableViewer(rightPanel, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
		mViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		
	}
	
	protected void buildMenus() {
		if (mListMenu != null) {
			mListMenu.dispose();
		}
		
		mListMenu = new Menu(mParent.getShell(), SWT.POP_UP);
		
		MenuItem openItem = new MenuItem(mListMenu, SWT.PUSH);
		openItem.setText(Messages.TaskListView_OpenMenuItem);
		openItem.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				openMenuHandler(e);
			}
		});
		
		new MenuItem(mListMenu, SWT.SEPARATOR);
		
		MenuItem manageTagsItem = new MenuItem(mListMenu, SWT.PUSH);
		manageTagsItem.setText(Messages.TaskListView_ManageTagsMenuItem);
		manageTagsItem.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				manageTagsMenuHandler(e);
			}
		});
		manageTagsItem.setImage(mTagsImage);
		
		MenuItem manageAttachmentsItem = new MenuItem(mListMenu, SWT.PUSH);
		manageAttachmentsItem.setText(Messages.BaseNoteListViewPart_ManageAttachments);
		manageAttachmentsItem.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				manageAttachmentsMenuHandler(e);
			}
		});
		manageAttachmentsItem.setImage(mAttachmentsImage);
		
		new MenuItem(mListMenu, SWT.SEPARATOR);
		
		MenuItem deleteItem = new MenuItem(mListMenu, SWT.PUSH);
		deleteItem.setText(Messages.TaskListView_DeleteMenuItem);
		deleteItem.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				deleteMenuHandler(e);
			}
		});
		deleteItem.setImage(mDeleteImage);
		
		mViewer.getTable().addListener(SWT.MenuDetect, new Listener() {
			public void handleEvent(Event event) {
				mListMenu.setVisible(true);
			}
		});
	}
	
	protected void fillTagsList() {
		mTagsList.removeAll();
		mFixedTagsList.removeAll();
		TableItem item;
		
		mAllTableItem = new TableItem(mFixedTagsList, SWT.NULL);
		mAllTableItem.setText(getAllTableItemText());
		mAllTableItem.setData(null);
		mAllTableItem.setImage(mEmptyTag);
		
		mUnTaggedTableItem = new TableItem(mFixedTagsList, SWT.NULL);
		mUnTaggedTableItem.setText(getUnTaggedTableItemText());
		mUnTaggedTableItem.setData(null);
		mUnTaggedTableItem.setImage(mNoTag);
		
		Tag tag;
		Iterator<Tag> iter = DataController.getInstance().getProject().getTagsList(getTagsSortDirection()).iterator();
		while (iter.hasNext()) {
			tag = iter.next();
			item = new TableItem(mTagsList, SWT.NULL);
			item.setText(String.format("%s (%s)", tag.getName(), getBaseNoteCountByTag(tag))); //$NON-NLS-1$
			item.setData(tag);
			item.setImage(mTag);
		}
		
		SortDirection currentSortDirection = getTagsSortDirection();
		switch (currentSortDirection) {
		case EnAscending : mTagsListColumn.setImage(mSortUpImage); break;
		case EnDescending : mTagsListColumn.setImage(mSortDownImage); break;
		}
	}
	
	protected void setTagSortDirection() {
		SortDirection newDirection = SortDirection.EnAscending;
		SortDirection currentDirection = getTagsSortDirection();
		
		switch (currentDirection) {
		case EnAscending : newDirection = SortDirection.EnDescending; break;
		case EnDescending : newDirection = SortDirection.EnAscending; break;
		}
		
		Controller.getInstance().getPreferenceStore().setValue(PreferenceConstants.NOTESLIST_TAGS_SORT_DIRECTION, newDirection.getValue());
		setTagsSortDirection(newDirection);
		
		fireTagsSortEvent();
	}
	
	public void dispose() {
		mTag.dispose();
		mNoTag.dispose();
		mEmptyTag.dispose();
		
		mTagsImage.dispose();
		mAttachmentsImage.dispose();
		mDeleteImage.dispose();
		
		mSortUpImage.dispose();
		mSortDownImage.dispose();
		
		super.dispose();
	}
	
}
